【教程】從零開始搭建 k3s 集群

提示:本教程基於 Linux + fish shell 編寫,個別命令語法與 Bash 略有差異。請結合自己的系統環境調整命令。
引言
眾所周知,k3s 是由 Rancher Labs 開發的輕量級 Kubernetes 發行版,也是目前最流行的 K8s 輕量化方案。
相較於傳統運維方式(1Panel/寶塔/SSH 等),k3s 的學習曲線更陡峭,需要理解更多容器編排概念。但一旦掌握,你將獲得:
k3s 的核心優勢
- 輕量高效 - 單個二進制文件,內存佔用 < 512MB,完美適配低配 VPS
- 生產就緒 - 完全兼容 Kubernetes API,可平滑遷移到標準 K8s
- 聲明式運維 - 用 YAML 描述期望狀態,系統自動維護
- 高可用保障 - 自動故障恢復 + 多節點負載均衡
- 開箱即用 - 內置網絡、存儲、Ingress 等核心組件
通過 k3s,我們可以將多台廉價 VPS 整合為企業級高可用集群,實現傳統運維難以達到的自動化水平。
目標讀者與準備
適合人群
- 有一定 Linux 基礎的開發者
- 希望從傳統運維過渡到容器編排
- 想搭建個人高可用服務的技術愛好者
前置知識
- 熟悉 Linux 命令行操作
- 了解 Docker 容器基礎
- 具備基本的網絡知識(SSH、防火牆)
學習收獲
完成本教程後,你將掌握:
- 使用 k3sup 快速部署 k3s 集群
- 理解 k3s 核心組件(API Server、etcd、kubelet 等)的作用
- 替換默認組件優化性能(Cilium CNI、Nginx Ingress 等)
- 部署第一個應用並配置外部訪問
- 基本的集群運維和故障排查技巧
部署規劃
k3s 默認安裝了一套精簡組件,為了滿足生產級訴求,我們需要提前規劃哪些模塊要保留或替換。下表展示了推薦的取捨策略:
| 組件類型 | k3s 默認組件 | 替換組件 | 替換理由 | k3sup 禁用參數 |
|---|---|---|---|---|
| 容器運行時 | containerd | - | 保持默認即可 | - |
| 數據存儲 | SQLite / etcd | - | 單節點用 SQLite,集群用 etcd | - |
| Ingress Controller | Traefik | Nginx Ingress / 其他 | 團隊更熟悉、功能需求不同 | --disable traefik |
| LoadBalancer | Service LB (Klipper-lb) | 不想部署 | 懶得管負載均衡,直接買 cloudflare | --disable servicelb |
| DNS | CoreDNS | - | 保持默認即可 | - |
| Storage Class | Local-path-provisioner | Longhorn | 分佈式存儲、高可用、備份能力 | --disable local-storage |
| CNI | Flannel | Cilium | eBPF 性能、網絡策略、可觀測性 | --flannel-backend=none --disable-network-policy |

環境準備
必備工具
首先,確保 k3sup、kubectl、Helm 等工具已正確安裝(可參考各自 GitHub 項目提供的安裝說明):
k3sup version
kubectl version
helm version
如圖所示:

服務器要求
準備至少三台雲服務器(示例環境使用 Ubuntu 24.04),作為最小化三節點高可用控制平面(推薦配置 ≥ 4C4G)。提前記錄各節點 IP、確認 SSH 公鑰已分發,並知曉本地私鑰路徑,後續步驟會用到。
部署初始控制平面
使用 k3sup 部署初始控制節點:
k3sup install \
--ip 初始節點 IP \
--user root \
--ssh-key 密鑰位置 \
--k3s-channel latest \
--cluster \
--k3s-extra-args "--disable traefik --disable servicelb --disable local-storage --flannel-backend=none --disable-network-policy"
如圖所示:

安裝完成後,k3sup 會自動將 kubeconfig 複製到當前目錄。雖然可以直接使用這份配置,但更加穩健的做法是與現有配置文件合併。
合併 kubeconfig
- 備份當前的 kubeconfig(默認位於
~/.kube/config):
cp ~/.kube/config ~/.kube/config.backup
fish shell(僅供參考):
cp $KUBECONFIG {$KUBECONFIG}.backup
- 將新舊 kubeconfig 合併為一份扁平文件:
KUBECONFIG=~/.kube/config:./kubeconfig kubectl config view --flatten > ~/.kube/config.new
fish shell(僅供參考):
KUBECONFIG=$KUBECONFIG:./kubeconfig kubectl config view --flatten > kubeconfig-merged.yaml
- 檢查新文件內容無誤後覆蓋舊配置:
mv ~/.kube/config.new ~/.kube/config
fish shell:
mv ./kubeconfig-merged.yaml $KUBECONFIG
- 驗證新上下文是否生效:
kubectl config get-contexts
kubectl config use-context default
安裝 Cilium(替代 Flannel)
安裝 k3s 時我們禁用了默認 CNI(Flannel),因此節點暫時無法互通。按計劃部署 Cilium 以提供網絡與網絡策略能力。
使用 Helm 安裝 Cilium:
# 添加 Cilium Helm 倉庫
helm repo add cilium https://helm.cilium.io/
# 更新 Helm 倉庫
helm repo update
# 安裝 Cilium CNI(單副本,默認模式)
helm install cilium cilium/cilium \
--namespace kube-system \
--set operator.replicas=1 \
--set ipam.mode=kubernetes
如果集群已經禁用 kube-proxy,可額外添加
--set kubeProxyReplacement=strict。本教程保持默認值以兼容更多場景。
執行完成後可以看到:

等待 Cilium 組件啟動完成:
# 查看 Cilium 相關 Pod 狀態
kubectl get pods -n kube-system -l k8s-app=cilium
# 查看節點狀態(應該從 NotReady 變為 Ready)
kubectl get nodes

節點切換到 Cilium 後應當從 NotReady 變為 Ready。接下來使用 k3sup 加入另外兩個控制節點。
擴容控制平面
為了實現高可用,我們需要至少 3 個控制節點。使用以下命令加入第二個控制節點:
k3sup join \
--ip 第二個節點 IP \
--user root \
--ssh-key 密鑰位置 \
--server-ip 初始節點 IP \
--server \
--k3s-channel latest \
--k3s-extra-args "--disable traefik --disable servicelb --disable local-storage --flannel-backend=none --disable-network-policy"
同樣的方式加入第三個控制節點:
k3sup join \
--ip 第三個節點 IP \
--user root \
--ssh-key 密鑰位置 \
--server-ip 初始節點 IP \
--server \
--k3s-channel latest \
--k3s-extra-args "--disable traefik --disable servicelb --disable local-storage --flannel-backend=none --disable-network-policy"
等待幾分鐘後檢查集群狀態:
kubectl get nodes
當三個控制節點均處於 Ready 狀態時,控制平面即告搭建完成。

安裝 Nginx Ingress Controller
替換 k3s 默認的 Traefik,安裝 Nginx Ingress Controller:
# 添加 Nginx Ingress Helm 倉庫
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# 安裝 Nginx Ingress Controller(可能需要等待很久)
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.hostPort.enabled=true \
--set controller.hostPort.ports.http=80 \
--set controller.hostPort.ports.https=443 \
--set controller.service.type=ClusterIP
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

安裝 Longhorn 分佈式存儲
Longhorn 是由 Rancher 開發的雲原生分佈式塊存儲系統,提供高可用、備份、快照等企業級功能。相比 k3s 默認的 local-path-provisioner,Longhorn 支持跨節點的持久化存儲。
前置依賴檢查
在安裝 Longhorn 之前,需要確保每個節點都安裝了必要依賴;若希望通過 Ansible 批量處理,可參考後續示例:
# 在每個節點上執行(通過 SSH)
# 檢查並安裝 open-iscsi
apt update
apt install -y open-iscsi nfs-common
# 啟動並設置開機自啟
systemctl enable --now iscsid
systemctl status iscsid
如果希望使用 Ansible 批量安裝依賴,可以參考以下任務片段:
---
- name: Setup K3s nodes with Longhorn dependencies and CrowdSec
hosts: k3s
become: true
vars:
crowdsec_version: "latest"
tasks:
# ============================================
# Longhorn Prerequisites
# ============================================
- name: Install Longhorn required packages
ansible.builtin.apt:
name:
- open-iscsi # iSCSI support for volume mounting
- nfs-common # NFS support for backup target
- util-linux # Provides nsenter and other utilities
- curl # For downloading and API calls
- jq # JSON processing for Longhorn CLI
state: present
update_cache: true
tags: longhorn
- name: Enable and start iscsid service
ansible.builtin.systemd:
name: iscsid
enabled: true
state: started
tags: longhorn
- name: Load iscsi_tcp kernel module
community.general.modprobe:
name: iscsi_tcp
state: present
tags: longhorn
- name: Ensure iscsi_tcp loads on boot
ansible.builtin.lineinfile:
path: /etc/modules-load.d/iscsi.conf
line: iscsi_tcp
create: true
mode: '0644'
tags: longhorn
- name: Check if multipathd is installed
ansible.builtin.command: which multipathd
register: multipathd_check
failed_when: false
changed_when: false
tags: longhorn
- name: Disable multipathd if installed (conflicts with Longhorn)
ansible.builtin.systemd:
name: multipathd
enabled: false
state: stopped
when: multipathd_check.rc == 0
tags: longhorn
部署 Longhorn
使用 Helm 安裝 Longhorn:
# 添加 Longhorn Helm 倉庫
helm repo add longhorn https://charts.longhorn.io
helm repo update
# 安裝 Longhorn(可能需要等待較長時間),請注意這裡為了節約硬盤空間,只設置了單副本,請根據需求自行調整
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--create-namespace \
--set defaultSettings.defaultDataPath="/var/lib/longhorn" \
--set persistence.defaultClass=true \
--set persistence.defaultClassReplicaCount=1
等待 Longhorn 組件啟動:
# 查看 Longhorn 組件狀態
kubectl get pods -n longhorn-system
# 查看 StorageClass
kubectl get storageclass

訪問 Longhorn UI(可選)
Longhorn 提供了一個 Web UI 用於管理存儲卷。可以通過端口轉發臨時訪問:
# 端口轉發到本地
kubectl port-forward -n longhorn-system svc/longhorn-frontend 8081:80
# 在瀏覽器訪問 http://localhost:8081
完成查看後,請在終端按
Ctrl+C停止端口轉發,避免持續佔用本地端口。
加入 Agent 節點
目前為止,我們搭建了一個 3 節點的高可用控制平面(control-plane)。在生產環境中,我們不希望在 control-plane 節點上運行實際的應用程序(會佔用 API Server、etcd 等核心組件的資源)。
因此,我們需要加入專門用於運行工作負載(Pods)的 Agent 節點(也稱為 Worker 節點)。
安裝前置依賴
與 control-plane 節點一樣,Agent 節點也需要滿足 Longhorn 的依賴(若希望這些節點能夠調度並存儲持久卷)。
在所有準備加入的 Agent 節點上,提前執行以下命令:
# 在每個 Agent 節點上執行(通過 SSH)
apt update
apt install -y open-iscsi nfs-common
# 啟動並設置開機自啟
systemctl enable --now iscsid
執行加入命令
添加 Agent 節點的命令與添加 control-plane 節點幾乎一致,但有兩個關鍵區別:不使用 --server 標記且無需額外參數。
k3sup join \
--ip <AGENT_節點 IP> \
--user root \
--ssh-key <密鑰位置> \
--server-ip <任意 Control 節點 IP> \
--k3s-channel latest
驗證節點狀態
可以一次性加入多個 Agent 節點。添加完成後等待幾分鐘,Cilium 與 Longhorn 的組件會自動調度到新節點。
使用 kubectl 查看集群狀態:
kubectl get nodes -o wide
你應該能看到新加入的節點,其 ROLE 列顯示為 <none>(在 k3s 中,<none> 即代表 agent/worker 角色)。
同時,你可以監控 Cilium 和 Longhorn 的 Pod 是否在新節點上成功啟動:
# Cilium agent 應該會在新節點上啟動
kubectl get pods -n kube-system -o wide
# Longhorn instance-manager 應該也會在新節點上啟動
kubectl get pods -n longhorn-system -o wide
至此,集群已經擁有了高可用的控制平面和用於運行應用的工作節點。
下一步行動
- 配置 Argo CD、Flux 等 GitOps 工具,將集群聲明式管理流程標準化。
- 部署 Prometheus、Loki、Grafana 等可觀測性組件,完善監控與日誌體系。
- 使用 Ansible Playbook 自動化節點初始化與組件升級,降低後續運維成本。